//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_okr_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/org_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_okr_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

type OrgOkrApiImpl struct {
	org_okr_api.UnimplementedOrgOkrApiServer
}

func (apiImpl *OrgOkrApiImpl) Create(ctx context.Context, req *org_okr_api.CreateRequest) (*org_okr_api.CreateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_okr_api.CreateResponse{
			Code:   org_okr_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.CreateResponse{
			Code:   org_okr_api.CreateResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.CreateResponse{
			Code:   org_okr_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	okrId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		okrItemList := []org_dao.OkrItemInfoDbItem{}
		for _, okrItem := range req.OkrItemList {
			okrItemList = append(okrItemList, org_dao.OkrItemInfoDbItem{
				Objective:     okrItem.Objective,
				KeyResultList: okrItem.KeyResultList,
			})
		}
		err = org_dao.OkrDao.Insert(sessCtx, &org_dao.OkrInfoDbItem{
			OkrId:        okrId,
			OrgId:        req.OrgId,
			MemberUserId: sessionItem.UserId,
			OkrItemList:  okrItemList,
			StartTime:    req.StartTime,
			EndTime:      req.EndTime,
			CreateTime:   nowTime,
			UpdateTime:   nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &org_okr_api.CreateResponse{
			Code:  org_okr_api.CreateResponse_CODE_OK,
			OkrId: okrId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_okr_api.CreateResponse), nil
}

func (apiImpl *OrgOkrApiImpl) Update(ctx context.Context, req *org_okr_api.UpdateRequest) (*org_okr_api.UpdateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_okr_api.UpdateResponse{
			Code:   org_okr_api.UpdateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.UpdateResponse{
			Code:   org_okr_api.UpdateResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.UpdateResponse{
			Code:   org_okr_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err = org_dao.OkrDao.Exist(ctx, req.OrgId, sessionItem.UserId, req.OkrId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.UpdateResponse{
			Code:   org_okr_api.UpdateResponse_CODE_NO_OKR,
			ErrMsg: "OKR不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		okrItemList := []org_dao.OkrItemInfoDbItem{}
		for _, okrItem := range req.OkrItemList {
			okrItemList = append(okrItemList, org_dao.OkrItemInfoDbItem{
				Objective:     okrItem.Objective,
				KeyResultList: okrItem.KeyResultList,
			})
		}
		err = org_dao.OkrDao.Update(sessCtx, req.OrgId, sessionItem.UserId, req.OkrId, okrItemList, req.StartTime, req.EndTime, nowTime)
		if err != nil {
			return nil, err
		}
		return &org_okr_api.UpdateResponse{
			Code: org_okr_api.UpdateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_okr_api.UpdateResponse), nil
}

func (apiImpl *OrgOkrApiImpl) List(ctx context.Context, req *org_okr_api.ListRequest) (*org_okr_api.ListResponse, error) {
	emptyList := []*org_okr_api.OkrInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_okr_api.ListResponse{
			Code:    org_okr_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:  "会话不存在",
			OkrList: emptyList,
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_okr_api.ListResponse{
			Code:    org_okr_api.ListResponse_CODE_NO_ORG,
			ErrMsg:  "组织不存在",
			OkrList: emptyList,
		}, nil
	}
	curMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return &org_okr_api.ListResponse{
			Code:    org_okr_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:  "没有权限",
			OkrList: emptyList,
		}, nil
	}
	targetMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, req.MemberUserId)
	if err != nil {
		return &org_okr_api.ListResponse{
			Code:    org_okr_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:  "没有权限",
			OkrList: emptyList,
		}, nil
	}
	//检查部门层级关系
	if !(orgItem.OwnerUserId == sessionItem.UserId || req.MemberUserId == sessionItem.UserId || curMemberItem.ParentDepartMentId == "") {
		include, err := utils.CheckIncludeDepartMent(ctx, req.OrgId, targetMemberItem.ParentDepartMentId, curMemberItem.ParentDepartMentId)
		if err != nil {
			return nil, err
		}
		if !include {
			return &org_okr_api.ListResponse{
				Code:    org_okr_api.ListResponse_CODE_NO_PERMISSION,
				ErrMsg:  "没有权限",
				OkrList: emptyList,
			}, nil
		}
	}

	count, err := org_dao.OkrDao.Count(ctx, req.OrgId, req.MemberUserId)
	if err != nil {
		return nil, err
	}

	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{req.MemberUserId})
	if err != nil {
		return nil, err
	}
	okrItemList, err := org_dao.OkrDao.List(ctx, req.OrgId, req.MemberUserId, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}

	//生成结果
	okrList := []*org_okr_api.OkrInfo{}
	for _, okrItem := range okrItemList {
		okr := okrItem.ToOkrInfo()
		if len(userItemList) == 1 {
			okr.MemberDisplayName = userItemList[0].BasicInfo.DisplayName
			okr.MemberLogoUri = userItemList[0].BasicInfo.LogoUri
		}
		okrList = append(okrList, okr)
	}

	return &org_okr_api.ListResponse{
		Code:       org_okr_api.ListResponse_CODE_OK,
		TotalCount: count,
		OkrList:    okrList,
	}, nil
}

func (apiImpl *OrgOkrApiImpl) Get(ctx context.Context, req *org_okr_api.GetRequest) (*org_okr_api.GetResponse, error) {
	emptyInfo := &org_okr_api.OkrInfo{
		OkrItemList: []*org_okr_api.OkrItemInfo{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_okr_api.GetResponse{
			Code:   org_okr_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Okr:    emptyInfo,
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_okr_api.GetResponse{
			Code:   org_okr_api.GetResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
			Okr:    emptyInfo,
		}, nil
	}

	curMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return &org_okr_api.GetResponse{
			Code:   org_okr_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Okr:    emptyInfo,
		}, nil
	}
	targetMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, req.MemberUserId)
	if err != nil {
		return &org_okr_api.GetResponse{
			Code:   org_okr_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Okr:    emptyInfo,
		}, nil
	}

	//检查部门层级关系
	if !(orgItem.OwnerUserId == sessionItem.UserId || req.MemberUserId == sessionItem.UserId || curMemberItem.ParentDepartMentId == "") {
		include, err := utils.CheckIncludeDepartMent(ctx, req.OrgId, targetMemberItem.ParentDepartMentId, curMemberItem.ParentDepartMentId)
		if err != nil {
			return nil, err
		}
		if !include {
			return &org_okr_api.GetResponse{
				Code:   org_okr_api.GetResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Okr:    emptyInfo,
			}, nil
		}
	}

	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{req.MemberUserId})
	if err != nil {
		return nil, err
	}

	okrItem, err := org_dao.OkrDao.Get(ctx, req.OrgId, req.MemberUserId, req.OkrId)
	if err != nil {
		return nil, err
	}
	//生成结果
	okr := okrItem.ToOkrInfo()
	if len(userItemList) == 1 {
		okr.MemberDisplayName = userItemList[0].BasicInfo.DisplayName
		okr.MemberLogoUri = userItemList[0].BasicInfo.LogoUri
	}
	return &org_okr_api.GetResponse{
		Code: org_okr_api.GetResponse_CODE_OK,
		Okr:  okr,
	}, nil
}

func (apiImpl *OrgOkrApiImpl) Remove(ctx context.Context, req *org_okr_api.RemoveRequest) (*org_okr_api.RemoveResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_okr_api.RemoveResponse{
			Code:   org_okr_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.RemoveResponse{
			Code:   org_okr_api.RemoveResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.RemoveResponse{
			Code:   org_okr_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err = org_dao.OkrDao.Exist(ctx, req.OrgId, sessionItem.UserId, req.OkrId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_okr_api.RemoveResponse{
			Code: org_okr_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.OkrDao.Remove(sessCtx, req.OrgId, sessionItem.UserId, req.OkrId)
		if err != nil {
			return nil, err
		}
		return &org_okr_api.RemoveResponse{
			Code: org_okr_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_okr_api.RemoveResponse), nil
}
